﻿using Ongoal.Quotation.Common;
using Ongoal.Quotation.Common;
using Ongoal.Quotation.Service;
using Ongoal.Quotation.Service.Common;
using Ongoal.Quotation.Service.Interface;
using Ongoal.Quotation.Service.Model;
using Ongoal.Quotation.Service.Model.basemodel;
using Ongoal.Quotation.Service.Model.Sys;
using Ongoal.Quotation.Service.ViewModel;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ongoal.Quotation.Service
{
    /// <summary>
    /// 用户服务
    /// </summary>
    public class RoleService : ServiceBase, IRoleService
    {


        #region 角色CRUD
        /// <summary>
        /// 获取角色树
        /// </summary>
        /// <returns></returns>
        public object GetTreeRole(string keyword)
        {
            using (var db = Db.GetDbContext(String.Empty))
            {
                //List<Role> treelist = new List<Role>();
                //var all = db.Queryable<Role>().WhereIF(!string.IsNullOrEmpty(keyword), z => z.RoleName.Contains(keyword) || z.RoleCode.Contains(keyword)).Where(z => z.Deleted == 0).ToList();
                //foreach (var item in all)
                //{
                //    if (item.ParentID == 0)
                //    {
                //        treelist.Add(item);
                //    }
                //    else
                //    {
                //      var parent= all.Where(z => z.ID == item.ParentID).FirstOrDefault();
                //        if (parent != null)
                //        {
                //            if (parent.Children == null)
                //            {
                //                parent.Children = new List<Role>();
                //            }
                //            parent.Children.Add(item);
                //        }
                //        else
                //        {
                //            treelist.Add(item);
                //        }
                //    }
                //}
                //return all;



                //return db.Queryable<Role, Role>((z, j) => new object[] {
                //    JoinType.Left,
                //    z.ParentID == j.ID
                //}).Where((z, j) => z.Deleted == 0)
                //  .WhereIF(!string.IsNullOrEmpty(keyword), z => z.RoleName.Contains(keyword) || z.RoleCode.Contains(keyword))
                //  .Where(z => z.Deleted == 0).Select((z, j) => new
                //  {
                //      CreateTime = z.CreateTime,
                //      CreatorID = z.CreatorID,
                //      Deleted = z.Deleted,
                //      ModifyID = z.ModifyID,
                //      ModifyTime = z.ModifyTime,
                //      ID = z.ID,
                //      NodeLevel = z.NodeLevel,
                //      OrderCode = z.OrderCode,
                //      ParentID = z.ParentID,
                //      ParentName = j.RoleName,
                //      RoleCode = z.RoleCode,
                //      PropPath = z.PropPath,
                //      Remark = z.Remark,
                //      RoleName = z.RoleName,
                //      RoleType = z.RoleType
                //  }).ToList();

                List<Role> treelist = new List<Role>();
                var all = db.Queryable<Role>().Where(z => z.Deleted == 0).WhereIF(!string.IsNullOrEmpty(keyword),
                    z => z.RoleName.Contains(keyword) || z.RoleCode.Contains(keyword)).ToList();
                foreach (var item in all)
                {
                    var parent = all.Where(z => z.ID == item.ParentID).FirstOrDefault();
                    if (parent != null)
                    {
                        if (parent.Children == null)
                        {
                            parent.Children = new List<Role>();
                        }
                        parent.Children.Add(item);
                    }
                    else
                    {
                        treelist.Add(item);
                    }
                }
                return treelist;
            }
        }

        /// <summary>
        /// 添加角色
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool AddRole(Role entity)
        {
            try
            {
                checkdata(entity, 1);
                this.Insert<Role>(entity);
                return true;
            }
            catch (Exception e)
            {

                throw new Exception(e.Message);
            }

        }

        /// <summary>
        /// 修改角色
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool UpdateRole(Role entity)
        {
            try
            {
                checkdata(entity, 2);
                this.Update<Role>(entity);
                return true;
            }
            catch (Exception e)
            {

                throw new Exception(e.Message);
            }

        }
        public bool checkdata(Role model, int checktype)
        {
            using (var db = Db.GetDbContext(""))
            {
                if (checktype == 1) //新增
                {
                    if (db.Queryable<Role>().Any(z => z.RoleCode == model.RoleCode && z.ParentID == model.ParentID))
                    {
                        throw new Exception("编码已经存在");
                    }
                    if (db.Queryable<Role>().Any(z => z.RoleName == model.RoleName && z.ParentID == model.ParentID))
                    {
                        throw new Exception("名称已经存在");
                    }
                }
                else
                { //编辑
                    if (db.Queryable<Role>().Any(z => z.RoleCode == model.RoleCode && z.ID != model.ID && z.ParentID == model.ParentID))
                    {
                        throw new Exception("编码已经存在");
                    }
                    if (db.Queryable<Role>().Any(z => z.RoleName == model.RoleName && z.ID != model.ID && z.ParentID == model.ParentID))
                    {
                        throw new Exception("名称已经存在");
                    }
                }
                return true;

            }
        }

        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="Ids"></param>
        /// <returns></returns>
        public bool deleteRole(List<int> Ids)
        {
            try
            {
                return this.Delete<Role>(Ids.ToArray());
            }
            catch (Exception e)
            {

                throw new Exception(e.Message);
            }

        }
        #endregion

        #region 角色与用户关系
        /// <summary>
        /// 获取已经授权给角色的用户
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="keyword"></param>
        /// <param name="orgPost"></param>
        /// <returns></returns>
        public object GetUserRole(int roleId, string keyword, string orgPost)
        {

            using (var db = Db.GetDbContext(String.Empty))
            {
                var datalist = db.Queryable<Role, R_Role_User, T_Sys_User>((r, t, u) => new object[] {
                JoinType.Right,r.ID==t.RoleID,
                JoinType.Right,t.UserID==u.ID,
                }).Where((r, t, u) => r.ID == roleId)
                .WhereIF(!string.IsNullOrEmpty(keyword), (r, t, u) => u.UserName.Contains(keyword) || u.UserCode.Contains(keyword))
                .Select((r, t, u) => new
                {
                    ID = u.ID,
                    Sex = u.Sex,
                    UserType = u.UserType,
                    UserName = u.UserName,
                    UserCode = u.UserCode,
                    RelationID = t.ID,
                    DisplayName = u.DisplayName,
                }).ToList()
                .Select(u => new
                {
                    ID = u.ID,
                    Sex = u.Sex,
                    UserType = u.UserType,
                    UserName = u.UserName,
                    UserCode = u.UserCode,
                    RelationID = u.RelationID,
                    DisplayName = u.DisplayName,
                    Organize = new List<string>(),
                    Post = new List<string>()
                }).ToList();

                var uids = datalist.Select(s => s.ID).ToList();
                var ops = db.Queryable<R_User_Org>()
                    .LeftJoin<Organize>((uo, o) => uo.OrgID == o.ID)
                    .LeftJoin<Post>((uo, o, p) => uo.PostID == p.ID)
                    .Where(uo => uids.Contains(uo.UserID))
                    .Select((uo, o, p) => new { uid = uo.UserID, Organize = o, Post = p }).ToList();
                foreach (var item in datalist)
                {
                    item.Organize.AddRange(ops.Where(s => s.uid == item.ID).Select(s => s.Organize!.OrgName!).ToList());
                    item.Post.AddRange(ops.Where(s => s.uid == item.ID).Select(s => s.Post!.PostName!).ToList());
                }
                if(!string.IsNullOrEmpty(orgPost))
                    datalist = datalist.Where(s => s.Organize.Any(t => t.Contains(orgPost)) || s.Post.Any(t => t.Contains(orgPost))).ToList();
                return datalist;
            }
        }

        /// <summary>
        /// 获取还没有授权给角色的用户
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="keyword"></param>
        /// <param name="orgPost"></param>
        /// <returns></returns>
        public object GetNotUserRole(int roleId, string keyword, string orgPost)
        {

            using (var db = Db.GetDbContext(String.Empty))
            {
                var userids = db.Queryable<Role, R_Role_User, T_Sys_User>((r, t, u) => new object[] {
            JoinType.Right,r.ID==t.RoleID,
            JoinType.Right,t.UserID==u.ID,
            }).Where((r, t, u) => r.ID == roleId).Select((r, t, u) => new
            {
                ID = u.ID,
            }).ToList().Select(z => z.ID).ToList();
                var datalist = db.Queryable<T_Sys_User>().Where(u => !userids.Contains(u.ID)).WhereIF(!string.IsNullOrEmpty(keyword), u => u.UserName.Contains(keyword) || u.UserCode.Contains(keyword))
                .ToList()
                .Select(u => new
                {
                    ID = u.ID,
                    Sex = u.Sex,
                    UserType = u.UserType,
                    UserName = u.UserName,
                    UserCode = u.UserCode,
                    DisplayName = u.DisplayName,
                    Organize = new List<string>(),
                    Post = new List<string>()
                }).ToList();

                var uids = datalist.Select(s => s.ID).ToList();
                var ops = db.Queryable<R_User_Org>()
                    .LeftJoin<Organize>((uo, o) => uo.OrgID == o.ID)
                    .LeftJoin<Post>((uo, o, p) => uo.PostID == p.ID)
                    .Where(uo => uids.Contains(uo.UserID))
                    .Select((uo, o, p) => new { uid = uo.UserID, Organize = o, Post = p }).ToList();
                foreach (var item in datalist)
                {
                    item.Organize.AddRange(ops.Where(s => s.uid == item.ID).Select(s => s.Organize!.OrgName!).ToList());
                    item.Post.AddRange(ops.Where(s => s.uid == item.ID).Select(s => s.Post!.PostName!).ToList());
                }
                if (!string.IsNullOrEmpty(orgPost))
                    datalist = datalist.Where(s => s.Organize.Any(t => t.Contains(orgPost)) || s.Post.Any(t => t.Contains(orgPost))).ToList();
                return datalist;

            }
        }

        /// <summary>
        /// 分配用户
        /// </summary>
        /// <param name="uids"></param>
        /// <param name="roleid"></param>
        /// <returns></returns>
        public bool AddRoleUser(List<int> uids, int roleid)
        {
            using (var db = Db.GetDbContext(String.Empty))
            {
                List<R_Role_User> list = new List<R_Role_User>();
                foreach (var uid in uids)
                {
                    R_Role_User t = new R_Role_User
                    {
                        UserID = uid,
                        CreateTime = DateTime.Now,
                        CreatorID = this.CurrentUser.UserID,
                        ModifyID = this.CurrentUser.UserID,
                        ModifyTime = DateTime.Now,
                        RoleID = roleid
                    };
                    list.Add(t);
                }
                db.Insertable<R_Role_User>(list).ExecuteCommand();
                return true;
            }
        }
        /// <summary>
        /// 移除用户
        /// </summary>
        /// <param name="tids"></param>
        /// <returns></returns>
        public bool RemoveRoleUser(List<int> tids)
        {
            try
            {
                return this.Delete<R_Role_User>(tids.ToArray());
            }
            catch (Exception e)
            {

                throw new Exception(e.Message);
            }
        }
        #endregion

        #region 角色授权
        /// <summary>
        /// 获取权限列表
        /// </summary>
        /// <returns></returns>
        public object GetAuthorList(int RoleID)
        {
            using (var db = Db.GetDbContext(string.Empty))
            {
                if (CurrentUser.UserType == (int)EUserType.SuperAdmin)//管理员
                {
                    //已经授权的项目
                    var HasAuthor = GetHasAuthor(RoleID);
                    List<string> checkeds = new List<string>();
                    List<AuthorMenuTree> resultlist = new List<AuthorMenuTree>();
                    var MenutypeList = db.Queryable<Menutype>().ToList();
                    var alldata = db.Queryable<Menu, T_Sys_MenuOperate, T_Sys_Operate, T_Sys_MenuDataItem, T_Sys_DataItem>((z, u, s, t, y) => new object[] {
                   JoinType.Left,z.ID==u.MenuID,
                   JoinType.Left,u.OperateID==s.ID,
                   JoinType.Left,z.ID==t.MenuID,
                   JoinType.Left,t.DataItemID==y.ID
                   }).Where((z, u, s, t, y) => z.Deleted != 1).Select((z, u, s, t, y) => new
                   {
                       MenuID = z.ID,
                       MenuName = z.CNName,
                       MenuTypeId = z.MenuType,
                       MenuParentID = z.ParentID,
                       OperatereId = u.ID,
                       operateName = s.Name,
                       Dataitemreid = t.ID,
                       Dataitemname = y.Name
                   }).ToList();
                    var menu = from x in alldata
                               group x by new { x.MenuID, x.MenuName, x.MenuParentID, x.MenuTypeId } into g
                               select g;
                    //循环菜单类型
                    foreach (var typeitem in MenutypeList)
                    {
                        AuthorMenuTree typeTree = new AuthorMenuTree
                        {
                            ID = typeitem.ID,
                            Checked = false,
                            Name = typeitem.CNName,
                            ParentID = 0,
                            KeyID = ConvertTokey("MenuType", typeitem.ID),
                            type = TreeType.MenuType
                        };
                        var menutotype = menu.Where(z => z.Key.MenuTypeId == typeitem.ID).Select(z => new AuthorMenuTree
                        {
                            ID = z.Key.MenuID,
                            Name = z.Key.MenuName,
                            Checked = HasAuthor.MenuList.Contains(z.Key.MenuID),
                            type = TreeType.Menu,
                            KeyID = ConvertTokey("Menu", z.Key.MenuID),
                            ParentID = z.Key.MenuParentID
                        }).ToList();
                        //把已授权的菜单的keyID放入列表
                        checkeds.AddRange(menutotype.Where(z => z.Checked == true).Select(z => z.KeyID).ToList());
                        //菜单树
                        List<AuthorMenuTree> menutree = new List<AuthorMenuTree>();
                        foreach (var item in menutotype)
                        {
                            //获取操作权限
                            var operatelist = from x in alldata
                                              where x.MenuID == item.ID
                                              group x by new { x.OperatereId, x.operateName } into g
                                              select g;
                            if (operatelist != null && operatelist.Count() > 1)
                            {
                                AuthorMenuTree operatefolder = new AuthorMenuTree()
                                {
                                    ID = 0,
                                    KeyID = item.KeyID + "operate",
                                    Checked = false,
                                    Name = "操作权限",
                                    type = TreeType.OperateFloder

                                };
                                item.children.Add(operatefolder);
                                foreach (var operateitem in operatelist)
                                {
                                    if (operateitem.Key.OperatereId != 0)
                                    {
                                        AuthorMenuTree operater = new AuthorMenuTree()
                                        {
                                            ID = operateitem.Key.OperatereId,
                                            Checked = HasAuthor.OperateList.Contains(operateitem.Key.OperatereId),
                                            Name = operateitem.Key.operateName,
                                            type = TreeType.Operate,
                                            KeyID = ConvertTokey("Operate", operateitem.Key.OperatereId)
                                        };
                                        if (operater.Checked)
                                        {
                                            //把已授权的操作的keyID放入列表
                                            checkeds.Add(operater.KeyID);
                                        }
                                        operatefolder.children.Add(operater);
                                    }
                                }
                                //如果有操作权限则默认显示操作权限文件夹被选中
                                if (operatefolder.children.Where(z => z.Checked == true).Count() > 0)
                                {
                                    checkeds.Add(item.KeyID + "operate");
                                }
                            }
                            //获取数据权限
                            var dataitemlist = from x in alldata
                                               where x.MenuID == item.ID
                                               group x by new { x.Dataitemreid, x.Dataitemname } into g
                                               select g;
                            if (dataitemlist != null && dataitemlist.Count() > 1)
                            {
                                AuthorMenuTree dataitemfolder = new AuthorMenuTree()
                                {
                                    ID = 0,
                                    Checked = false,
                                    Name = "数据权限",
                                    type = TreeType.DataitemFloder,
                                    KeyID = item.KeyID + "dataitem"

                                };
                                item.children.Add(dataitemfolder);
                                foreach (var dataitem in dataitemlist)
                                {
                                    if (dataitem.Key.Dataitemreid != 0)
                                    {
                                        AuthorMenuTree dataitementity = new AuthorMenuTree()
                                        {
                                            ID = dataitem.Key.Dataitemreid,
                                            Checked = HasAuthor.DataItemList.Contains(dataitem.Key.Dataitemreid),
                                            Name = dataitem.Key.Dataitemname,
                                            type = TreeType.Dataitem,
                                            KeyID = ConvertTokey("dataitem", dataitem.Key.Dataitemreid)
                                        };
                                        if (dataitementity.Checked)
                                        {
                                            //把已授权的操作的keyID放入列表
                                            checkeds.Add(dataitementity.KeyID);
                                        }
                                        dataitemfolder.children.Add(dataitementity);
                                    }
                                }
                                //如果有数据权限则默认显示数据权限文件夹被选中
                                if (dataitemfolder.children.Where(z => z.Checked == true).Count() > 0)
                                {
                                    checkeds.Add(item.KeyID + "dataitem");
                                }
                            }

                            var parent = menutotype.Where(z => item.ParentID == z.ID).FirstOrDefault();
                            if (parent == null)
                            {
                                menutree.Add(item);
                            }
                            else
                            {
                                parent.children.Add(item);
                            }

                        }
                        typeTree.children.AddRange(menutree);
                        resultlist.Add(typeTree);
                        //如果有菜单被赋予权限则默认显示菜单类型被选中
                        if (typeTree.children.Where(z => z.Checked == true).Count() > 0)
                        {
                            checkeds.Add(ConvertTokey("MenuType", typeitem.ID));
                        }
                    }
                    var obj = new
                    {
                        resultlist = resultlist,
                        checkeds = checkeds
                    };
                    return obj;
                }
                return "";

            }
        }

        /// <summary>
        /// 获取已授权的项
        /// </summary>
        /// <param name="RoleID"></param>
        /// <returns></returns>
        public Authorformatter GetHasAuthor(int RoleID)
        {
            using (var db = Db.GetDbContext(string.Empty))
            {
                //角色菜单权限
                var authmenulist = db.Queryable<Role, R_Role_Menu, Menu, R_Role_MenuOperate, T_Sys_MenuOperate, R_Role_MenuDataItem, T_Sys_MenuDataItem>((z, u, s, o, q, i, t) => new object[]
                  {
                        JoinType.Left,z.ID==u.RoleID,
                        JoinType.Left,u.MenuID==s.ID,
                        JoinType.Left,z.ID==o.RoleID,
                        JoinType.Left,o.MenuOperateID==q.ID,
                        JoinType.Left,z.ID==i.RoleID,
                        JoinType.Left,i.MenuDataItem==t.ID,
                  }).Where((z, u, s, o, q, i, t) => z.ID == RoleID).Select((z, u, s, o, q, i, t) => new
                  {
                      MenuID = s.ID,
                      OperateID = q.ID,
                      DataItemID = t.ID
                  }).ToList();
                //授权的菜单
                var MenuList = authmenulist.GroupBy(Z => Z.MenuID).Select(z => z.Key).ToList();
                //授权的操作
                var OperateList = authmenulist.GroupBy(Z => Z.OperateID).Select(z => z.Key).ToList();
                //授权的数据项
                var DataItemList = authmenulist.GroupBy(Z => Z.DataItemID).Select(z => z.Key).ToList();
                var obj = new Authorformatter
                {
                    MenuList = MenuList,
                    OperateList = OperateList,
                    DataItemList = DataItemList
                };
                return obj;
            }
        }

        /// <summary>
        /// id转key
        /// </summary>
        /// <param name="type"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public string ConvertTokey(string type, int id)
        {
            return type + id.ToString();
        }
        /// <summary>
        /// 授权
        /// </summary>
        /// <param name="list"></param>
        /// <param name="RoleID"></param>
        /// <returns></returns>
        public object AddAuthor(List<AuthorMenuTree> list, int RoleID)
        {
            using (var db = Db.GetDbContext(string.Empty))
            {
                try
                {
                    var grouplist = list.GroupBy(z => z.type);
                    db.Ado.BeginTran();
                    db.Deleteable<R_Role_Menu>().Where(z => z.RoleID == RoleID).ExecuteCommand();//删除菜单授权
                    db.Deleteable<R_Role_MenuOperate>().Where(z => z.RoleID == RoleID).ExecuteCommand();//删除操作授权
                    db.Deleteable<R_Role_MenuDataItem>().Where(z => z.RoleID == RoleID).ExecuteCommand();//删除数据项授权
                    foreach (var item in grouplist)
                    {
                        switch (item.Key)
                        {
                            case TreeType.Menu: //菜单权限

                                List<R_Role_Menu> menulist = new List<R_Role_Menu>();
                                foreach (var queue in item)
                                {
                                    R_Role_Menu t = new R_Role_Menu()
                                    {
                                        RoleID = RoleID,
                                        CreateTime = DateTime.Now,
                                        CreatorID = CurrentUser.UserID,
                                        MenuID = queue.ID,
                                        ModifyID = CurrentUser.UserID,
                                        ModifyTime = DateTime.Now
                                    };
                                    menulist.Add(t);
                                }
                                db.Insertable<R_Role_Menu>(menulist).ExecuteCommand();
                                break;
                            case TreeType.Operate://操作权限

                                List<R_Role_MenuOperate> operatelist = new List<R_Role_MenuOperate>();
                                foreach (var queue in item)
                                {
                                    R_Role_MenuOperate t = new R_Role_MenuOperate()
                                    {
                                        RoleID = RoleID,
                                        CreateTime = DateTime.Now,
                                        CreatorID = CurrentUser.UserID,
                                        MenuOperateID = queue.ID,
                                        ModifyID = CurrentUser.UserID,
                                        ModifyTime = DateTime.Now
                                    };
                                    operatelist.Add(t);
                                }
                                db.Insertable<R_Role_MenuOperate>(operatelist).ExecuteCommand();
                                break;
                            case TreeType.Dataitem://数据权限
                                List<R_Role_MenuDataItem> dataitemlist = new List<R_Role_MenuDataItem>();
                                foreach (var queue in item)
                                {
                                    R_Role_MenuDataItem t = new R_Role_MenuDataItem()
                                    {
                                        RoleID = RoleID,
                                        CreateTime = DateTime.Now,
                                        CreatorID = CurrentUser.UserID,
                                        MenuDataItem = queue.ID,
                                        ModifyID = CurrentUser.UserID,
                                        ModifyTime = DateTime.Now
                                    };
                                    dataitemlist.Add(t);
                                }
                                db.Insertable<R_Role_MenuDataItem>(dataitemlist).ExecuteCommand();
                                break;
                            default:
                                break;
                        }
                    }
                    db.Ado.CommitTran();
                    return true;
                }
                catch (Exception e)
                {
                    db.Ado.CommitTran();
                    throw new Exception(e.Message);
                }
            }
        }

        #endregion
    }

}

